package com.ehome.plugin

import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Opcodes
import org.objectweb.asm.commons.AdviceAdapter


class EHomeActivityClassVisitor(api: Int, classVisitor: ClassVisitor?) : ClassVisitor(api, classVisitor) {
    private val TAG = EHomeActivityClassVisitor::class.simpleName

    private var hasOnCreateMethod = false
    private var hasOnRestartMethod = false
    private var hasOnStartMethod = false
    private var hasOnResumeMethod = false
    private var hasOnPauseMethod = false
    private var hasOnStopMethod = false
    private var hasWindowFocusMethod = false

    private var name: String? = null
    private var superName: String? = null

    constructor(classVisitor: ClassVisitor?) : this(api = Opcodes.ASM5, classVisitor)

    override fun visit(version: Int, access: Int, name: String?, signature: String?, superName: String?, interfaces: Array<out String>?) {
        super.visit(version, access, name, signature, superName, interfaces)
        this.name = name
        this.superName = superName

        println("$TAG#visit: name-> $name")
    }


    override fun visitMethod(access: Int, name: String?, descriptor: String?, signature: String?, exceptions: Array<out String>?): MethodVisitor {
        if (("onCreate" == (name)) and ("()V" == descriptor)) {
            hasOnCreateMethod = true
            val visitMethod = cv.visitMethod(access, name, descriptor, signature, exceptions)
            return object : AdviceAdapter(api, visitMethod, access, name, descriptor) {
                override fun onMethodEnter() {
                    super.onMethodEnter()
                    mv.visitVarInsn(Opcodes.ALOAD, 0)
                    mv.visitLdcInsn("page_onCreate")
                    mv.visitInsn(Opcodes.ICONST_1)
                    mv.visitMethodInsn(
                        Opcodes.INVOKESTATIC,
                        "com/efs/sdk/launch/LaunchManager",
                        "onTracePage",
                        "(Landroid/app/Activity;Ljava/lang/String;Z)V",
                        false
                    )
                    mv.visitVarInsn(Opcodes.ALOAD, 0)
                    mv.visitLdcInsn("onCreate")
                    mv.visitInsn(Opcodes.ICONST_1)
                    mv.visitMethodInsn(
                        Opcodes.INVOKESTATIC,
                        "com/umeng/pagesdk/PageManger",
                        "onTracePageBegin",
                        "(Landroid/app/Activity;Ljava/lang/String;Z)V",
                        true
                    )
                }

                override fun onMethodExit(opcode: Int) {
                    super.onMethodExit(opcode)
                    mv.visitVarInsn(Opcodes.ALOAD, 0)
                    mv.visitLdcInsn("onCreate")
                    mv.visitInsn(Opcodes.ICONST_1)
                    mv.visitMethodInsn(
                        Opcodes.INVOKESTATIC,
                        "com/umeng/pagesdk/PageManger",
                        "onTracePageEnd",
                        "(Landroid/app/Activity;Ljava/lang/String;Z)V",
                        true
                    )
                }
            }
        } else if (("onRestart" == name) and ("()V" == descriptor)) {
            hasOnRestartMethod = true
            val visitMethod = cv.visitMethod(access, name, descriptor, signature, exceptions)

            return object : AdviceAdapter(api, visitMethod, access, name, descriptor) {
                override fun onMethodEnter() {
                    super.onMethodEnter()
                    mv.visitVarInsn(Opcodes.ALOAD, 0)
                    mv.visitLdcInsn("page_onReStart")
                    mv.visitInsn(Opcodes.ICONST_1)
                    mv.visitMethodInsn(
                        Opcodes.INVOKESTATIC,
                        "com/efs/sdk/launch/LaunchManager",
                        "onTracePage",
                        "(Landroid/app/Activity;Ljava/lang/String;Z)V",
                        false
                    )
                }

                override fun onMethodExit(opcode: Int) {
                    super.onMethodExit(opcode)


                }
            }
        } else if (("onStart" == name) and ("()V" == descriptor)) {
            hasOnStartMethod = true
            val visitMethod = cv.visitMethod(access, name, descriptor, signature, exceptions)
            return object : AdviceAdapter(api, visitMethod, access, name, descriptor) {
                override fun onMethodEnter() {
                    super.onMethodEnter()
                    mv.visitVarInsn(Opcodes.ALOAD, 0)
                    mv.visitLdcInsn("page_onStart")
                    mv.visitInsn(Opcodes.ICONST_1)
                    mv.visitMethodInsn(
                        Opcodes.INVOKESTATIC,
                        "com/efs/sdk/launch/LaunchManager",
                        "onTracePage",
                        "(Landroid/app/Activity;Ljava/lang/String;Z)V",
                        false
                    )
                    mv.visitVarInsn(Opcodes.ALOAD, 0)
                    mv.visitLdcInsn("onStart")
                    mv.visitInsn(Opcodes.ICONST_1)
                    mv.visitMethodInsn(
                        Opcodes.INVOKESTATIC,
                        "com/umeng/pagesdk/PageManger",
                        "onTracePageBegin",
                        "(Landroid/app/Activity;Ljava/lang/String;Z)V",
                        true
                    )
                }

                override fun onMethodExit(opcode: Int) {
                    super.onMethodExit(opcode)
                    mv.visitVarInsn(Opcodes.ALOAD, 0)
                    mv.visitLdcInsn("onStart")
                    mv.visitInsn(Opcodes.ICONST_1)
                    mv.visitMethodInsn(
                        Opcodes.INVOKESTATIC,
                        "com/umeng/pagesdk/PageManger",
                        "onTracePageEnd",
                        "(Landroid/app/Activity;Ljava/lang/String;Z)V",
                        true
                    )
                }
            }
        } else if (("onResume" == name) and ("()V" == descriptor)) {
            hasOnResumeMethod = true
            val visitMethod = cv.visitMethod(access, name, descriptor, signature, exceptions)

            return object : AdviceAdapter(api, visitMethod, access, name, descriptor) {
                override fun onMethodEnter() {
                    super.onMethodEnter()
                    mv.visitVarInsn(Opcodes.ALOAD, 0)
                    mv.visitLdcInsn("onResume")
                    mv.visitInsn(Opcodes.ICONST_1)
                    mv.visitMethodInsn(
                        Opcodes.INVOKESTATIC,
                        "com/umeng/pagesdk/PageManger",
                        "onTracePageBegin",
                        "(Landroid/app/Activity;Ljava/lang/String;Z)V",
                        true
                    )
                }

                override fun onMethodExit(opcode: Int) {
                    super.onMethodExit(opcode)
                    mv.visitVarInsn(Opcodes.ALOAD, 0)
                    mv.visitLdcInsn("page_onResume")
                    mv.visitInsn(ICONST_0)
                    mv.visitMethodInsn(
                        Opcodes.INVOKESTATIC,
                        "com/efs/sdk/launch/LaunchManager",
                        "onTracePage",
                        "(Landroid/app/Activity;Ljava/lang/String;Z)V",
                        false
                    )
                    mv.visitVarInsn(Opcodes.ALOAD, 0)
                    mv.visitLdcInsn("onResume")
                    mv.visitInsn(Opcodes.ICONST_1)
                    mv.visitMethodInsn(
                        Opcodes.INVOKESTATIC,
                        "com/umeng/pagesdk/PageManger",
                        "onTracePageEnd",
                        "(Landroid/app/Activity;Ljava/lang/String;Z)V",
                        true
                    )
                }
            }
        } else if (("onPause" == name) and ("()V" == descriptor)) {
            hasOnPauseMethod = true
            val visitMethod = cv.visitMethod(access, name, descriptor, signature, exceptions)

            return object : AdviceAdapter(api, visitMethod, access, name, descriptor) {
                override fun onMethodEnter() {
                    super.onMethodEnter()
                    mv.visitVarInsn(Opcodes.ALOAD, 0)
                    mv.visitLdcInsn("onPause")
                    mv.visitInsn(Opcodes.ICONST_1)
                    mv.visitMethodInsn(
                        Opcodes.INVOKESTATIC,
                        "com/umeng/pagesdk/PageManger",
                        "onTracePageBegin",
                        "(Landroid/app/Activity;Ljava/lang/String;Z)V",
                        true
                    )
                }

                override fun onMethodExit(opcode: Int) {
                    super.onMethodExit(opcode)
                    mv.visitVarInsn(Opcodes.ALOAD, 0)
                    mv.visitLdcInsn("onPause")
                    mv.visitInsn(Opcodes.ICONST_1)
                    mv.visitMethodInsn(
                        Opcodes.INVOKESTATIC,
                        "com/umeng/pagesdk/PageManger",
                        "onTracePageEnd",
                        "(Landroid/app/Activity;Ljava/lang/String;Z)V",
                        true
                    )
                }
            }
        } else if (("onStop" == name) and ("()V" == descriptor)) {
            hasOnStopMethod = true
            val visitMethod = cv.visitMethod(access, name, descriptor, signature, exceptions)

            return object : AdviceAdapter(api, visitMethod, access, name, descriptor) {
                override fun onMethodEnter() {
                    super.onMethodEnter()
                    mv.visitVarInsn(Opcodes.ALOAD, 0)
                    mv.visitLdcInsn("page_onStop")
                    mv.visitInsn(Opcodes.ICONST_1)
                    mv.visitMethodInsn(
                        Opcodes.INVOKESTATIC,
                        "com/efs/sdk/launch/LaunchManager",
                        "onTracePage",
                        "(Landroid/app/Activity;Ljava/lang/String;Z)V",
                        false
                    )
                }

                override fun onMethodExit(opcode: Int) {
                    super.onMethodExit(opcode)
                }
            }
        } else {
            return super.visitMethod(access, name, descriptor, signature, exceptions)
        }
    }

    override fun visitEnd() {
        super.visitEnd()
        if (!hasOnCreateMethod) {
            insertOnCreateMethod(cv, superName)
        }

        if (!hasOnRestartMethod) {
            insertOnRestartMethod(cv, superName)
        }

        if (!hasOnStartMethod) {
            insertOnStartMethod(cv, superName)
        }

        if (!hasOnResumeMethod) {
            insertOnResumeMethod(cv, superName)
        }

        if (!hasOnPauseMethod) {
            insertOnPauseMethod(cv, superName)
        }

        if (!hasOnStopMethod) {
            insertOnStopMethod(cv, superName)
        }
    }

    private fun insertOnCreateMethod(cv: ClassVisitor, superName: String?) {
        val methodVisitor = cv.visitMethod(Opcodes.ACC_PROTECTED, "onCreate", "(Landroid/os/Bundle;)V", null as String?, null as Array<String?>?)
        methodVisitor.visitCode()
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0)
        methodVisitor.visitLdcInsn("page_onCreate")
        methodVisitor.visitInsn(Opcodes.ICONST_1)
        methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "com/efs/sdk/launch/LaunchManager", "onTracePage", "(Landroid/app/Activity;Ljava/lang/String;Z)V", false)
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0)
        methodVisitor.visitLdcInsn("onCreate")
        methodVisitor.visitInsn(Opcodes.ICONST_1)
        methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "com/umeng/pagesdk/PageManger", "onTracePageBegin", "(Landroid/app/Activity;Ljava/lang/String;Z)V", false)
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0)
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 1)
        methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, superName, "onCreate", "(Landroid/os/Bundle;)V", false)
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0)
        methodVisitor.visitLdcInsn("onCreate")
        methodVisitor.visitInsn(Opcodes.ICONST_1)
        methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "com/umeng/pagesdk/PageManger", "onTracePageEnd", "(Landroid/app/Activity;Ljava/lang/String;Z)V", false)
        methodVisitor.visitInsn(Opcodes.RETURN)
        methodVisitor.visitMaxs(3, 2)
        methodVisitor.visitEnd()
    }

    private fun insertOnRestartMethod(cv: ClassVisitor, superName: String?) {
        val methodVisitor = cv.visitMethod(Opcodes.ACC_PROTECTED, "onRestart", "()V", null as String?, null as Array<String?>?)
        methodVisitor.visitCode()
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0)
        methodVisitor.visitLdcInsn("page_onReStart")
        methodVisitor.visitInsn(Opcodes.ICONST_1)
        methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "com/efs/sdk/launch/LaunchManager", "onTracePage", "(Landroid/app/Activity;Ljava/lang/String;Z)V", false)
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0)
        methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, superName, "onRestart", "()V", false)
        methodVisitor.visitInsn(Opcodes.RETURN)
        methodVisitor.visitMaxs(3, 1)
        methodVisitor.visitEnd()
    }

    private fun insertOnStartMethod(cv: ClassVisitor, superName: String?) {
        val methodVisitor = cv.visitMethod(Opcodes.ACC_PROTECTED, "onStart", "()V", null as String?, null as Array<String?>?)
        methodVisitor.visitCode()
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0)
        methodVisitor.visitLdcInsn("page_onStart")
        methodVisitor.visitInsn(Opcodes.ICONST_1)
        methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "com/efs/sdk/launch/LaunchManager", "onTracePage", "(Landroid/app/Activity;Ljava/lang/String;Z)V", false)
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0)
        methodVisitor.visitLdcInsn("onStart")
        methodVisitor.visitInsn(Opcodes.ICONST_1)
        methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "com/umeng/pagesdk/PageManger", "onTracePageBegin", "(Landroid/app/Activity;Ljava/lang/String;Z)V", false)
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0)
        methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, superName, "onStart", "()V", false)
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0)
        methodVisitor.visitLdcInsn("onStart")
        methodVisitor.visitInsn(Opcodes.ICONST_1)
        methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "com/umeng/pagesdk/PageManger", "onTracePageEnd", "(Landroid/app/Activity;Ljava/lang/String;Z)V", false)
        methodVisitor.visitInsn(Opcodes.RETURN)
        methodVisitor.visitMaxs(3, 1)
        methodVisitor.visitEnd()
    }

    private fun insertOnResumeMethod(cv: ClassVisitor, superName: String?) {
        val methodVisitor = cv.visitMethod(Opcodes.ACC_PROTECTED, "onResume", "()V", null as String?, null as Array<String?>?)
        methodVisitor.visitCode()
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0)
        methodVisitor.visitLdcInsn("onResume")
        methodVisitor.visitInsn(Opcodes.ICONST_1)
        methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "com/umeng/pagesdk/PageManger", "onTracePageBegin", "(Landroid/app/Activity;Ljava/lang/String;Z)V", false)
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0)
        methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, superName, "onResume", "()V", false)
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0)
        methodVisitor.visitLdcInsn("onResume")
        methodVisitor.visitInsn(Opcodes.ICONST_1)
        methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "com/umeng/pagesdk/PageManger", "onTracePageEnd", "(Landroid/app/Activity;Ljava/lang/String;Z)V", false)
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0)
        methodVisitor.visitLdcInsn("page_onResume")
        methodVisitor.visitInsn(3)
        methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "com/efs/sdk/launch/LaunchManager", "onTracePage", "(Landroid/app/Activity;Ljava/lang/String;Z)V", false)
        methodVisitor.visitInsn(Opcodes.RETURN)
        methodVisitor.visitMaxs(3, 1)
        methodVisitor.visitEnd()
    }

    private fun insertOnPauseMethod(cv: ClassVisitor, superName: String?) {
        val methodVisitor = cv.visitMethod(Opcodes.ACC_PROTECTED, "onPause", "()V", null as String?, null as Array<String?>?)
        methodVisitor.visitCode()
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0)
        methodVisitor.visitLdcInsn("onPause")
        methodVisitor.visitInsn(Opcodes.ICONST_1)
        methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "com/umeng/pagesdk/PageManger", "onTracePageBegin", "(Landroid/app/Activity;Ljava/lang/String;Z)V", false)
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0)
        methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, superName, "onPause", "()V", false)
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0)
        methodVisitor.visitLdcInsn("onPause")
        methodVisitor.visitInsn(Opcodes.ICONST_1)
        methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "com/umeng/pagesdk/PageManger", "onTracePageEnd", "(Landroid/app/Activity;Ljava/lang/String;Z)V", false)
        methodVisitor.visitInsn(Opcodes.RETURN)
        methodVisitor.visitMaxs(3, 1)
        methodVisitor.visitEnd()
    }

    private fun insertOnStopMethod(cv: ClassVisitor, superName: String?) {
        val methodVisitor = cv.visitMethod(Opcodes.ACC_PROTECTED, "onStop", "()V", null as String?, null as Array<String?>?)
        methodVisitor.visitCode()
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0)
        methodVisitor.visitLdcInsn("page_onStop")
        methodVisitor.visitInsn(Opcodes.ICONST_1)
        methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "com/efs/sdk/launch/LaunchManager", "onTracePage", "(Landroid/app/Activity;Ljava/lang/String;Z)V", false)
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0)
        methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, superName, "onStop", "()V", false)
        methodVisitor.visitInsn(Opcodes.RETURN)
        methodVisitor.visitMaxs(3, 1)
        methodVisitor.visitEnd()
    }

}